#include "lcd.h"
#include "lv_port_disp.h"

// 把 lcd 显存区域看成一个二维数组
typedef uint16_t (*pFramebuffer)[1024];


/* LCD 区域填充函数 - DMA2D 存储器到存储器模式 */
void lcd_fill_area_with_pixmap(uint16_t xStart, uint16_t yStart, uint16_t width, uint16_t height, uint16_t* pixmap)
{
    // 把 lcd 显存区域看成一个二维数组
    pFramebuffer framebuffer = (pFramebuffer)0xC0000000;

    DMA2D->CR = DMA2D_M2M;                                      // 设置 DMA2D 为寄存器到存储器模式
    DMA2D->OMAR = (uint32_t)&framebuffer[yStart][xStart];       // 设置填充区域的起始内存地址
    DMA2D->NLR  = (uint32_t)(width << 16) | (uint16_t)height;   // 设置矩形区域的宽和高
    DMA2D->OOR = 1024 - width;                                  // 设置行偏移，即跳过的像素
    DMA2D->FGMAR = (uint32_t)pixmap;                            // 前景层像素源所处内存首地址
    DMA2D->FGOR = 0;                                            // 前景层偏移，因为图像数据在 pixmap 是连续存在的，所以此处偏移值为 0
    DMA2D->CR |= DMA2D_CR_TCIE;                                 // 传输完成中断使能
    DMA2D->CR |= DMA2D_CR_START;                                // 开启 DMA2D 的数据传输
    // while (DMA2D->CR & DMA2D_CR_START);                      // 等待 DMA2D 传输完成
}

/* LCD 区域填充函数 - DMA2D 寄存器到存储器模式*/
void lcd_fill_area_with_color(uint16_t xStart, uint16_t yStart, uint16_t width, uint16_t height, uint16_t color)
{
    // 把 lcd 显存区域看成一个二维数组
    pFramebuffer framebuffer = (pFramebuffer)0xC0000000;

    #if 0
    for(uint16_t y = yStart; y < yStart + height; y++)
    {
        for(uint16_t x = xStart; x < xStart + width; x++)
        {
            framebuffer[y][x] = color;
        }
    }
    #endif
    DMA2D->CR = DMA2D_R2M;                                      // 设置 DMA2D 为寄存器到存储器模式
    DMA2D->OMAR = (uint32_t)&framebuffer[yStart][xStart];       // 设置填充区域的起始内存地址
    DMA2D->NLR  = (uint32_t)(width << 16) | (uint16_t)height;   // 设置矩形区域的宽和高
    DMA2D->OOR = 1024 - width;                                  // 设置行偏移，即跳过的像素
    DMA2D->OCOLR = color;                                       // 设置填充使用的颜色
    DMA2D->CR |= DMA2D_CR_TCIE;                                 // 传输完成中断使能
    DMA2D->CR |= DMA2D_CR_START;                                // 开启 DMA2D 的数据传输
    // while (DMA2D->CR & DMA2D_CR_START);                      // 等待 DMA2D 传输完成
}

/* LCD 打点 */
void lcd_draw_point(uint16_t x, uint16_t y, uint16_t color)
{
    // 把 lcd 显存区域看成一个二维数组
    pFramebuffer framebuffer = (pFramebuffer)0xC0000000;
    framebuffer[y][x] = color;
}

/* LCD 区域填充完成回调 */
#include "lvgl.h"
extern lv_display_t* glv_display;
void lcd_fill_finished(void)
{
    lv_display_flush_ready(glv_display);
}

